import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


public class CoderBioctets {
	Map<String, Integer> freqMap = new HashMap<String, Integer>();
	Map<String, Integer> tableCode = new HashMap<String, Integer>();
	Map<Integer, String> inverseTableCode = new HashMap<Integer , String>();
	
	//generate the references
	public CoderBioctets(String filePath)
	{
	
		String bioctetReaded;
		byte[] buffer = new byte[2];
		try{
			System.out.println("Coder start! Initializing...");
			/*
			 * Comtage et Tri des bioctets
			 */
			int bytes_read;
			FileInputStream inputStream = new FileInputStream(filePath);
			while((bytes_read = inputStream.read(buffer)) != -1){
				bioctetReaded = "" + (char)buffer[0] + (char)buffer[1];
				
				if (!freqMap.containsKey(bioctetReaded)){
					freqMap.put(bioctetReaded, 1);
				}else{
					freqMap.put(bioctetReaded, freqMap.get(bioctetReaded) + 1);
				}
			}
			
			
			List<String> bioctets = new ArrayList<String>(freqMap.keySet());
			Collections.sort(bioctets, new KeyComparator(freqMap));
			
			/*
			 * Table de codes
			 */
			BufferedWriter out = new BufferedWriter(new FileWriter("tableCode.txt"));
			int n=0; // l'ordre de la clef dans la liste triee bioctets
			//les seuils
			int max1Byte = 128; 	//2^7=128 bioctets les plus frequents
			int min2Byte = 32767 + 128; 	//2^15-1=32767 bioctets suivants
	
			for(String key : bioctets){				
				int code = 0;
				if (n<max1Byte){
					code = n;//1 bit a 0 suivi de 7 bits
				}
				else if((n>=max1Byte) && (n<min2Byte)){
					code = (n - 128) | (1<<15); //1 bit a 1 suivi de 15 bits 
				}
				else { //les restants qui sont les plus rares, voire inexistant
					code = n | (65535<<16); //16 bits a 1 (0xffff=65535) suivis de la valeur d'entree 
				}
				tableCode.put(key, code);
				inverseTableCode.put(code, key);
				//System.out.println(keys.size());
//				System.out.println("key : " + key + " - frequency : " + n + " - code: " + bioctets.get(key));
				String str = "key : " + key + " - frequency : " + freqMap.get(key) + " - code: " + tableCode.get(key) + " - binary: " + Integer.toBinaryString(tableCode.get(key)) + "\n";
				out.write(str);
				n++;
			}
			
			inputStream.close();
			out.close();
			
			System.out.println("Coder init done!");
			
		}catch (Exception e) {
			System.out.print(e);
		}
	}
	
	public int getCode(String inputBioctet) {
		int bioctetsCoded;	
		bioctetsCoded = tableCode.get(inputBioctet);
		return bioctetsCoded;		
	}
		
	public String getString(int code) {
		String str;	
		str = inverseTableCode.get(code);
		return str;		
	}
	
}